/*
*****************************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2002-2012, Advanced Audio Video Coding Standard, Part II
*
* DISCLAIMER OF WARRANTY
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations under
* the License.
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY.
* The AVS Working Group doesn't represent or warrant that the programs
* furnished here under are free of infringement of any third-party patents.
* Commercial implementations of AVS, including shareware, may be
* subject to royalty fees to patent holders. Information regarding
* the AVS patent policy for standardization procedure is available at
* AVS Web site http://www.avs.org.cn. Patent Licensing is outside
* of AVS Working Group.
*
* The Initial Developer of the Original Code is Video subgroup of AVS
* Workinggroup.
* Contributors: Qin Yu,         Zhichu He,  Weiran Li,    Yong Ling,
*               Zhenjiang Shao, Jie Chen,   Junjun Si,    Xiaozhen Zheng, 
*               Jian Lou,       Qiang Wang, Jianwen Chen, Haiwu Zhao,
*               Guoping Li,     Siwei Ma,   Junhao Zheng, Zhiming Wang
*               Li Zhang,
******************************************************************************
*/
#include "intra-prediction.h"


#define Clip(x)            ( min(255, max( 0, (x)) ) )															///< clip with bit-depth range




/////////////////////////////////////////////////////////////////////////////
/// variables definition
/////////////////////////////////////////////////////////////////////////////
const unsigned char g_aucXYflg[NUM_INTRA_PMODE]=
{
  0,0,0,0,0,
  0,0,0,0,0,
  0,0,0,0,0,
  0,0,0,0,0,
  0,0,0,0,0,
  1,1,1,1,1,
  1,1,1
};

const char g_aucDirDx[NUM_INTRA_PMODE] =
{
  0,0,0,11,2,
  11,1,8,1,4,
  1,1,0,1,1,
  4,1,8,1,11,
  2,11,4,8,0,
  8,4,11,2,11,
  1,8,1
};

const char g_aucDirDy[NUM_INTRA_PMODE] =
{
  0,0,0,-4,-1,
  -8,-1,-11,-2,-11,
  -4,-8,0,8,4,
  11,2,11,1,8,
  1,4,1,1,0,
  -1,-1,-4,-1,-8,
  -1,-11,-2
};

#if SIMP_PRED_ADI
const char g_aucSign[NUM_INTRA_PMODE]=
{
  0, 0, 0,-1,-1,
  -1,-1,-1,-1,-1,
  -1,-1, 0, 1, 1,
  1, 1, 1, 1, 1,
  1, 1, 1, 1, 0,
  -1,-1,-1,-1,-1,
  -1,-1,-1
};
const char g_aucDirDxDy[2][NUM_INTRA_PMODE][2] =
{
  { // dx/dy
    {0, 0}, {0,0}, {0,0}, {11,2}, {2,0},
    {11,3}, {1,0}, {93,7}, {1,1}, {93,8}, 
    {1,2}, {1,3}, {0,0}, {1,3}, {1,2},
    {93,8}, {1,1}, {93,7}, {1,0}, {11,3}, 
    {2,0}, {11,2}, {4,0}, {8,0}, {0,0}, 
    {8,0}, {4,0}, {11,2}, {2,0},{11,3},
    {1,0}, {93,7},{1,1},
  },
  { // dy/dx
    {0, 0}, {0,0}, {0,0}, {93,8}, {1,1},
    {93,7}, {1,0}, {11,3}, {2,0}, {11,2},
    {4,0}, {8,0}, {0,0}, {8,0}, {4,0},
    {11,2}, {2,0},{11,3}, {1,0}, {93,7},
    {1,1}, {93,8}, {1,2}, {1,3}, {0,0}, 
    {1,3}, {1,2}, {93,8}, {1,1}, {93,7}, 
    {1,0}, {11,3}, {2,0}
    }
};
#endif

/////////////////////////////////////////////////////////////////////////////
/// local function declaration
/////////////////////////////////////////////////////////////////////////////
static void xPredIntraVertAdi( short* pSrc, int ** pDst, int iWidth, int iHeight );
static void xPredIntraHorAdi( short* pSrc, int ** pDst, int iWidth, int iHeight );
#if EXTEND_BD
static void xPredIntraDCAdi( short* pSrc, int ** pDst, int iWidth, int iHeight, int bAboveAvail, int bLeftAvail, int sample_bit_depth );
static void xPredIntraPlaneAdi( short* pSrc, int ** pDst, int iWidth, int iHeight, int sample_bit_depth );
static void xPredIntraBiAdi( short* pSrc, int ** pDst, int iWidth, int iHeight, int sample_bit_depth );
#else
static void xPredIntraDCAdi( short* pSrc, int ** pDst, int iWidth, int iHeight, int bAboveAvail, int bLeftAvail );
static void xPredIntraPlaneAdi( short* pSrc, int ** pDst, int iWidth, int iHeight );
static void xPredIntraBiAdi( short* pSrc, int ** pDst, int iWidth, int iHeight );
#endif
static void xPredIntraAngAdi( short* pSrc, int ** pDst, int uiDirMode, int iWidth, int iHeight );
#if SIMP_PRED_ADI
static int  getContextPixel( int uiDirMode, int uiXYflag, int iTempD, int* offset );
#else
static int  getContextPixel( int uiDirMode, int uiXYflag, int iTempD, Boolean* bCenter, int* offset );
#endif

/////////////////////////////////////////////////////////////////////////////
/// function definition
/////////////////////////////////////////////////////////////////////////////
void xPredIntraVertAdi( short* pSrc, int ** pDst, int iWidth, int iHeight )
{  
	int x, y;
	short* rpSrc = pSrc + 1;

	for ( y = 0; y < iHeight; y++ )
	{
		for (x = 0; x < iWidth; x++)
		{
			pDst[y][x]=rpSrc[x];
		}
	}
}

void xPredIntraHorAdi( short* pSrc, int ** pDst, int iWidth, int iHeight )
{
	int x, y;
	short* rpSrc = pSrc - 1;

	for ( y = 0; y < iHeight; y++ )
	{
		for ( x = 0; x < iWidth; x++ )
		{
			pDst[y][x]=rpSrc[-y];
		}
	}
}
#if EXTEND_BD
void xPredIntraDCAdi( short* pSrc, int ** pDst, int iWidth, int iHeight, int bAboveAvail, int bLeftAvail, int sample_bit_depth )
#else
void xPredIntraDCAdi( short* pSrc, int ** pDst, int iWidth, int iHeight, int bAboveAvail, int bLeftAvail )
#endif
{
	int   x, y;
	int   iDCValue = 0;
	short*  rpSrc = pSrc - 1;

	if (bLeftAvail )
	{
		for ( y = 0; y < iHeight; y++ )
		{
			iDCValue += rpSrc[-y];
		}

		rpSrc = pSrc + 1;
		if (bAboveAvail )
		{
			for ( x = 0; x < iWidth; x++ )
			{
				iDCValue += rpSrc[x];
			}

#if M3460_DC_MUL_REMOVE
			iDCValue += ((iWidth+iHeight)>>1);
			iDCValue=(iDCValue*(512/(iWidth + iHeight)))>>9;

#else
			iDCValue += iWidth;
			iDCValue /= iWidth + iHeight;
#endif
		}
		else
		{
			iDCValue += iHeight / 2;
			iDCValue /= iHeight;
		}
	}
	else
	{
		rpSrc = pSrc + 1;
		if (bAboveAvail)
		{
			for ( x = 0; x < iWidth; x++ )
			{
				iDCValue += rpSrc[x];
			}

			iDCValue += iWidth / 2;
			iDCValue /= iWidth;
		}
		else
		{
#if EXTEND_BD
			iDCValue = 1 << (sample_bit_depth - 1);
#else
			iDCValue = 128;
#endif
		}
	}

	for ( y = 0; y < iHeight; y++ )
	{
		for ( x = 0; x < iWidth; x++ )
		{
			pDst[y][x]=iDCValue;
		}
	}
}

#if EXTEND_BD
void xPredIntraPlaneAdi(short* pSrc, int ** pDst, int iWidth, int iHeight, int sample_bit_depth )
#else
void xPredIntraPlaneAdi(short* pSrc, int ** pDst, int iWidth, int iHeight )
#endif
{
	int iH = 0;
	int iV = 0;
	int iA, iB, iC;
	int x, y;
	int iW2 = iWidth>>1;
	int iH2 = iHeight>>1;
#if PLANE_SDIP_FIX
#if SIMP_PRED_PLANE
  int ib_mult[5]={13, 17, 5, 11, 23};
  int ib_shift[5]={7, 10, 11, 15,19};

  int im_h=ib_mult[g_log2size[iWidth]-2];
  int is_h=ib_shift[g_log2size[iWidth]-2];
  int im_v=ib_mult[g_log2size[iHeight]-2];
  int is_v=ib_shift[g_log2size[iHeight]-2];

#else
  int iWeight_H=iW2 * ( iW2 + 1 ) * ( (iW2<<1) + 1 );
  int iWeight_V=iH2 * ( iH2 + 1 ) * ( (iH2<<1) + 1 );
#endif
#else
	int iWeight = 0;
#endif
	int iTmp, iTmp2;

	short*  rpSrc = pSrc;

	rpSrc = pSrc + 1;
	rpSrc += (iW2 - 1);
	for ( x = 1; x < iW2+1; x++ )
	{
		iH += x * (rpSrc[x] - rpSrc[-x]);
	}

	rpSrc = pSrc - 1;
	rpSrc -= (iH2 - 1);

  for( y = 1; y < iH2+1; y++ )
  {
    iV += y * (rpSrc[-y] - rpSrc[y]);
  }

	rpSrc = pSrc;
#if PLANE_SDIP_FIX
  iA = ( rpSrc[-1 - (iHeight-1)] + rpSrc[1 + iWidth-1] ) << 4;
#if SIMP_PRED_PLANE
  iB = ( (iH<<5)*im_h + (1<<(is_h-1)) ) >> is_h;
  iC = ((iV<<5)*im_v + (1<<(is_v-1)) ) >> is_v;
#else
  iB = ( 3*(iH<<5) + (iWeight_H>>1) ) / iWeight_H;
  iC = ( 3*(iV<<5) + (iWeight_V>>1) ) / iWeight_V;
#endif
#else
	iWeight = iW2 * ( iW2 + 1 ) * ( (iW2<<1) + 1 );
	iA = ( rpSrc[-1 - (iHeight-1)] + rpSrc[1 + iWidth-1] ) << 4;
	iB = ( 3*(iH<<5) + (iWeight>>1) ) / iWeight;
	iC = ( 3*(iV<<5) + (iWeight>>1) ) / iWeight;
#endif

  iTmp = iA - (iH2-1)*iC - (iW2-1)*iB + 16;
	for ( y = 0; y < iHeight; y++ )
	{
		iTmp2 = iTmp;
		for ( x = 0; x < iWidth; x++ )
		{
			//img->mprr[PLANE_PRED][y][x] = Clip( iTmp2 >> 5 );
#if EXTEND_BD
			pDst[y][x]=Clip3(0, (1 << sample_bit_depth) - 1, iTmp2 >> 5 );
#else
			pDst[y][x]=Clip( iTmp2 >> 5 );
#endif
			iTmp2 += iB;
		}
		iTmp += iC;
	}
}

#if EXTEND_BD
void xPredIntraBiAdi( short* pSrc, int ** pDst, int iWidth, int iHeight, int sample_bit_depth )
#else
void xPredIntraBiAdi( short* pSrc, int ** pDst, int iWidth, int iHeight )
#endif
{
#if SIMP_PRED_BI
  int x, y;
  int ishift_x=g_log2size[iWidth];
  int ishift_y=g_log2size[iHeight];
  int ishift=min(ishift_x,ishift_y);
  int ishift_xy=ishift_x+ishift_y+1;
  int offset=1<<(ishift_x+ishift_y);
  int a,b,c,w,wxy,tmp;
  int predx;
  short pTop[MAX_CU_SIZE], pLeft[MAX_CU_SIZE], pT[MAX_CU_SIZE], pL[MAX_CU_SIZE],wy[MAX_CU_SIZE];

  for( x=0; x<iWidth; x++)
  {
    pTop[x] = pSrc[1+x];
  }
  for( y=0; y<iHeight; y++)
  {
    pLeft[y] = pSrc[-1-y];
  }

  a = pTop[iWidth-1];
  b = pLeft[iHeight-1];
  c=(iWidth==iHeight) ? (a+b+1)>>1 : (((a<<ishift_x) + (b<<ishift_y))*13 + (1<<(ishift+5)) ) >>(ishift+6);
  w=(c<<1)-a-b;


  for ( x=0; x<iWidth; x++)
  {
    pT[x]=b-pTop[x];
    pTop[x] <<=ishift_y;
  }
  tmp=0;
  for ( y=0; y<iHeight; y++)
  {
    pL[y]=a-pLeft[y];
    pLeft[y] <<=ishift_x;
    wy[y]=tmp;
    tmp+=w;
  }


  for( y=0; y<iHeight; y++ )
  {
    predx=pLeft[y];
    wxy=0;
    for( x=0; x<iWidth; x++ )
    {
      predx+=pL[y];
      wxy+=wy[y];
      pTop[x]+=pT[x];
      pDst[y][x] = ( (predx<<ishift_y) + (pTop[x]<<ishift_x) + wxy + offset )>> ishift_xy ;
    }
  }
#else
	int x, y;
	int iW2 = iWidth >> 1;
	int iH2 = iHeight >> 1;

	short* pCorner =  pSrc + 1; // pCorner[x] - points 0...iWidth-1 along x axis
	short* pDown = pSrc - 1 - ( iHeight - 1 ); // pDown[0] - left down pixel
#if BILINEAR_SDIP_FIX
	int a = ( pCorner[iWidth - 1] * iWidth + pDown[0] * iHeight + iW2 + iH2 ) / ( iWidth  + iHeight ) ;
#else
	int a = ( pCorner[iWidth - 1] * iHeight + pDown[0] * iWidth + iW2 + iH2 ) / ( iWidth  + iHeight ) ;
#endif

	int ky = ( a - pCorner[iWidth - 1] ); // the slope along vertical right
	int kx = ( a - pDown[0] );       // the slope along horizontal down

	int pRight;
	short* pY;
	int kxIntermediate, kyIntermediate;
	int xVal, yVal, pxDown;

	for ( y = 0; y < iHeight; y++ )
	{
		// intermediate line
		pY = pSrc - 1 - y; // pY[0] - left point

		if ( ky >= 0 )
		{
			pRight = pCorner[iWidth - 1] + ( ( ky * ( y + 1 ) + iH2 ) / iHeight );
		}
		else
		{
			pRight = pCorner[iWidth - 1] + ( ( ky * ( y + 1 ) - iH2 ) / iHeight );
		}

		kxIntermediate = ( pRight - pY[0] );

		for ( x = 0; x < iWidth; x++ )
		{
			if ( kxIntermediate >= 0 )
			{
				xVal = pY[0] + ( ( kxIntermediate * ( x + 1 ) + iW2 ) / iWidth );
			}
			else
			{
				xVal = pY[0] + ( ( kxIntermediate * ( x + 1 ) - iW2 ) / iWidth );
			}

			if ( kx >= 0 )
			{
				pxDown = pDown[0] + ( ( kx * ( x + 1 ) + iW2 ) / iWidth );
			}
			else
			{
				pxDown = pDown[0] + ( ( kx * ( x + 1 ) - iW2 ) / iWidth );
			}

			kyIntermediate = ( pxDown - pCorner[x] );
			if ( kyIntermediate >= 0 )
			{
				yVal = pCorner[x] + ( ( kyIntermediate * ( y + 1 ) + iH2 ) / iHeight );
			}
			else
			{
				yVal = pCorner[x] + ( ( kyIntermediate * ( y + 1 ) - iH2 ) / iHeight );
			}

			if ( ( xVal * iHeight + yVal * iWidth ) >= 0 )
			{
#if EXTEND_BD
				pDst[y][x] = Clip3( 0, (1 << sample_bit_depth) - 1, ( xVal * iHeight + yVal * iWidth + iW2 + iH2 ) / ( iWidth  + iHeight ) );
#else
				pDst[y][x] = Clip( ( xVal * iHeight + yVal * iWidth + iW2 + iH2 ) / ( iWidth  + iHeight ) );
#endif
			}
			else
			{
#if EXTEND_BD
				pDst[y][x] = Clip3(0, (1 << sample_bit_depth) - 1, ( xVal * iHeight + yVal * iWidth - iW2 - iH2 ) / ( iWidth  + iHeight ) );
#else
				pDst[y][x] = Clip( ( xVal * iHeight + yVal * iWidth - iW2 - iH2 ) / ( iWidth  + iHeight ) );
#endif
			}
		}
	}
#endif
}
#if SIMP_PRED_ADI
int getContextPixel(int uiDirMode, int uiXYflag, int iTempD, int* offset)
#else
int getContextPixel(int uiDirMode, int uiXYflag, int iTempD, Boolean* bCenter, int* offset)
#endif
{
#if SIMP_PRED_ADI
  int imult= g_aucDirDxDy[uiXYflag][uiDirMode][0];
  int ishift= g_aucDirDxDy[uiXYflag][uiDirMode][1];

  int iTempDn = iTempD * imult >> ishift;
  *offset = ((iTempD * imult * 32) >> ishift) - iTempDn*32;
	return iTempDn;
#else
	int iTempDn = 0;

  int iDxt = g_aucDirDx[uiDirMode];
  int iDyt = g_aucDirDy[uiDirMode];
  int iDx = abs(g_aucDirDx[uiDirMode]);
  int iDy = abs(g_aucDirDy[uiDirMode]);


	if ( uiXYflag == 0 )
	{
		iTempDn = iDx * iTempD / iDy;
		*offset = iDx * iTempD * 32 / iDy - iTempDn*32;

		if ( ( iDx * iTempD ) % iDy == 0 ) 
		{
			*bCenter = TRUE;
		}
		else 
		{
			*bCenter = FALSE;
		}
	}
	else
	{
		iTempDn = iDy * iTempD / iDx;
		*offset = iDy * iTempD * 32 / iDx - iTempDn * 32;

		if ( ( iDy * iTempD ) % iDx == 0 ) 
		{ 
			*bCenter = TRUE;
		}
		else 
		{
			*bCenter = FALSE;
		}
	}
	return iTempDn;
#endif
}
void xPredIntraAngAdi( short* pSrc, int ** pDst, int uiDirMode, int iWidth, int iHeight )
{
	int  iDx, iDy, i, j, iTempDx, iTempDy, iXx, iXy, iYx, iYy;
	int  uixyflag = 0; // 0 for x axis 1 for y axis
	Boolean bSetFlag1, bSetFlag2;
#if !SIMP_PRED_ADI
	Boolean bCenterx, bCentery, bCenter;
#endif
	int offset, offsetx, offsety;
    int iX, iY, iXn, iYn, iXnN1, iYnN1, iXnP2, iYnP2;
	int iDxy;
	int iDxP, iDxN, iDyP, iDyN;
	int iWidth2 = iWidth << 1;
	int iHeight2 = iHeight << 1;
	short*  rpSrc = pSrc;
    iDx = g_aucDirDx[ uiDirMode ];
    iDy = g_aucDirDy[ uiDirMode ];
    uixyflag = g_aucXYflg[ uiDirMode ];
#if SIMP_PRED_ADI
    iDxy = g_aucSign[uiDirMode];
#else
	iDxy = iDx * iDy;
#endif

  for ( j = 0, iDyP = iDy, iDyN = -iDy; j < iHeight; j++, iDyP++, iDyN++ )
  {
    for ( i = 0, iDxP = iDx, iDxN = -iDx; i < iWidth; i++, iDxP++, iDxN++ )
    {
      bSetFlag1 = FALSE;
      bSetFlag2 = FALSE;

      if ( ( iDyP >= 0 ) && ( iDyP < iHeight ) && ( iDxP >= 0 ) && ( iDxP < iWidth ) )
        if ( pDst[iDyP][iDxP] > 0 )
        {
          bSetFlag1 = TRUE;
        }

        if ( !bSetFlag1 )
          if ( ( iDyN >= 0 ) && ( iDyN < iHeight ) && ( iDxN >= 0 ) && ( iDxN < iWidth ) )
            if ( pDst[ iDyN][iDxN ] > 0 )
            {
              bSetFlag2 = TRUE;
            }

            if ( bSetFlag1 )
            {
              pDst[j][i] = pDst[iDyP][iDxP];
            }
            else if ( bSetFlag2 )
            {
              pDst[j][i] = pDst[iDyN][iDxN ];
            }
            else
            {
              if ( iDxy < 0 )   // select context pixel based on uixyflag
              {
                if ( uixyflag == 0 )
                {
                  // case xline
                  iTempDy = j - ( -1 );
#if SIMP_PRED_ADI
                  iTempDx = getContextPixel( uiDirMode, 0, iTempDy, &offset );
#else
                  iTempDx = getContextPixel( uiDirMode, 0, iTempDy, &bCenter, &offset );
#endif
                  iX = i + iTempDx;
                  iY = -1;
                }
                else
                {
                  // case yline
                  iTempDx = i - ( -1 );
#if SIMP_PRED_ADI
                  iTempDy = getContextPixel( uiDirMode, 1, iTempDx, &offset );
#else
                  iTempDy = getContextPixel( uiDirMode, 1, iTempDx, &bCenter, &offset );
#endif
                  iX = -1;
                  iY = j + iTempDy;
                }
              }
              else  // select context pixel based on the distance
              {
                iTempDy = j - ( -1 );
#if SIMP_PRED_ADI
                iTempDx = getContextPixel( uiDirMode, 0, iTempDy, &offsetx );
#else
                iTempDx = getContextPixel( uiDirMode, 0, iTempDy, &bCenterx, &offsetx );
#endif
                iTempDx = -iTempDx;
                iXx = i + iTempDx;
                iYx = -1;

                iTempDx = i - ( -1 );
#if SIMP_PRED_ADI
                iTempDy = getContextPixel( uiDirMode, 1, iTempDx, &offsety );
#else
                iTempDy = getContextPixel( uiDirMode, 1, iTempDx, &bCentery, &offsety );
#endif
                iTempDy = -iTempDy;
                iXy = -1;
                iYy = j + iTempDy;

                if ( iYy <= -1 )
                {
                  iX = iXx;
                  iY = iYx;
#if !SIMP_PRED_ADI
                  bCenter = bCenterx;
#endif
                  offset = offsetx;
                }
                else
                {
                  iX = iXy;
                  iY = iYy;
#if !SIMP_PRED_ADI
                  bCenter = bCentery;
#endif
                  offset = offsety;
                }
              }

              if ( iY == -1 )
              {
                if ( iX < -1 )
                {
                  iX = -1;
                }
                else if ( iX >= iWidth2 )
                {
                  iX = iWidth2 - 1;
                }
              }
              else if ( iX == -1 )
              {
                if ( iY < -1 )
                {
                  iY = -1;
                }
                else if ( iY >= iHeight2 )
                {
                  iY = iHeight2 - 1;
                }
              }

              if ( iY == -1 )
              {
                rpSrc = pSrc + 1;

                if ( iDxy < 0 )
                {
                  iXn = iX + 1;
                }
                else
                {
                  iXn = iX - 1;
                }

                if ( iXn >= iWidth2 )
                {
                  iXn = iWidth2 - 1;
                }

                if ( iDxy < 0 )
                {
                  iXnP2 = iX + 2;
                  iXnN1 = iX - 1;
                }
                else
                {
                  iXnP2 = iX - 2;
                  iXnN1 = iX + 1;
                }

                if ( iXnP2 >= iWidth2 )
                {
                  iXnP2 = iWidth2 - 1;
                }

                if ( iXnN1 >= iWidth2 )
                {
                  iXnN1 = iWidth2 - 1;
                }

                pDst[j][i] = ( rpSrc[iXnN1] * ( 32 - offset ) + rpSrc[iX] * ( 64 - offset ) + rpSrc[iXn] * ( 32 + offset ) + rpSrc[iXnP2] * offset + 64 ) >> 7;
              }
              else if ( iX == -1 )
              {
                rpSrc = pSrc - 1;

                if ( iDxy < 0 )
                {
                  iYn = iY + 1;
                }
                else
                {
                  iYn = iY - 1;
                }

                if ( iYn >= iHeight2 )
                {
                  iYn = iHeight2 - 1;
                }

                if ( iDxy < 0 )
                {
                  iYnP2 = iY + 2;
                  iYnN1 = iY - 1;
                }
                else
                {
                  iYnP2 = iY - 2;
                  iYnN1 = iY + 1;
                }

                if ( iYnP2 >= iHeight2 )
                {
                  iYnP2 = iHeight2 - 1;
                }

                if ( iYnN1 >= iHeight2 )
                {
                  iYnN1 = iHeight2 - 1;
                }
                pDst[j][i] = ( rpSrc[-iYnN1] * ( 32 - offset ) + rpSrc[-iY] * ( 64 - offset ) + rpSrc[-iYn] * ( 32 + offset ) + rpSrc[-iYnP2] * offset + 64 ) >> 7;
              }
            }
    }
  }
}

#if EXTEND_BD
void predIntraLumaAdi(short* pSrc, int** piPredBuf,int uiDirMode, unsigned int uiBitSize, int bAbove, int bLeft,int bs_y,int bs_x, int sample_bit_depth )
#else
void predIntraLumaAdi(short* pSrc, int** piPredBuf,int uiDirMode, unsigned int uiBitSize, int bAbove, int bLeft,int bs_y,int bs_x )
#endif
{


	switch( uiDirMode )
	{
	case VERT_PRED:  // Vertical
		{
			xPredIntraVertAdi( pSrc, piPredBuf, bs_x, bs_y );   
			break;
		}
	case HOR_PRED:  // Horizontal
		{
			xPredIntraHorAdi( pSrc, piPredBuf, bs_x, bs_y  );
			break;      
		}
	case DC_PRED:  // DC
		{
#if EXTEND_BD
			xPredIntraDCAdi( pSrc, piPredBuf, bs_x, bs_y , bAbove, bLeft, sample_bit_depth );
#else
			xPredIntraDCAdi( pSrc, piPredBuf, bs_x, bs_y , bAbove, bLeft );
#endif
			break;
		}
	case PLANE_PRED:  // Plane
		{
#if EXTEND_BD
			xPredIntraPlaneAdi( pSrc, piPredBuf, bs_x, bs_y, sample_bit_depth  );
#else
			xPredIntraPlaneAdi( pSrc, piPredBuf, bs_x, bs_y  );
#endif
			break;
		}
	case BI_PRED:  // bi
		{
#if EXTEND_BD
			xPredIntraBiAdi ( pSrc, piPredBuf, bs_x, bs_y, sample_bit_depth  );
#else
			xPredIntraBiAdi ( pSrc, piPredBuf, bs_x, bs_y  );
#endif
			break;
		}
	default:
		{
			xPredIntraAngAdi(pSrc, piPredBuf, uiDirMode,bs_x, bs_y );
			break;
		}
	}
}

#if EXTEND_BD
void predIntraChromaAdi( short * pSrc, int** piPredBuf, int uiDirMode, unsigned int uiBitSize, int bAbove, int bLeft, int LumaMode, int sample_bit_depth )
#else
void predIntraChromaAdi( short * pSrc, int** piPredBuf, int uiDirMode, unsigned int uiBitSize, int bAbove, int bLeft, int LumaMode )
#endif
{
	int uiWidth = 1 << uiBitSize;
	int uiHeight = 1 << uiBitSize;

  if( uiDirMode == DM_PRED_C && ( LumaMode == VERT_PRED || LumaMode == HOR_PRED || LumaMode == DC_PRED || LumaMode == BI_PRED ))
	{
		uiDirMode = LumaMode==VERT_PRED ? VERT_PRED_C : ( LumaMode==HOR_PRED ? HOR_PRED_C : ( LumaMode==DC_PRED ?  DC_PRED_C : BI_PRED_C ) );
	}

	switch( uiDirMode )
	{
  case DM_PRED_C: // DM
	  {
		  switch( LumaMode )
		  {
		  case PLANE_PRED:  // Plane
			  {
#if EXTEND_BD
				  xPredIntraPlaneAdi( pSrc, piPredBuf, uiWidth, uiHeight, sample_bit_depth );
#else
					xPredIntraPlaneAdi( pSrc, piPredBuf, uiWidth, uiHeight );
#endif
				  break;
			  }
		  default:
			  {
				  xPredIntraAngAdi( pSrc, piPredBuf, LumaMode, uiWidth, uiHeight );
				  break;
			  }
		  }
		  break;
	  }
  case DC_PRED_C:  // DC
	  {
#if EXTEND_BD
		  xPredIntraDCAdi( pSrc, piPredBuf, uiWidth, uiHeight, bAbove,  bLeft, sample_bit_depth );
#else
			xPredIntraDCAdi( pSrc, piPredBuf, uiWidth, uiHeight, bAbove,  bLeft );
#endif
		  break;
	  }
  case HOR_PRED_C:  // Horizontal
	  {
		  xPredIntraHorAdi( pSrc, piPredBuf, uiWidth, uiHeight );
		  break;      
	  }
  case VERT_PRED_C:  // Vertical
	  {
		  xPredIntraVertAdi( pSrc, piPredBuf, uiWidth, uiHeight );   
		  break;
	  }
  case BI_PRED_C: // Bilinear
	  {
#if EXTEND_BD
		  xPredIntraBiAdi ( pSrc, piPredBuf, uiWidth, uiHeight, sample_bit_depth );
#else
			xPredIntraBiAdi ( pSrc, piPredBuf, uiWidth, uiHeight );
#endif
		  break;
	  }
  default:
	  {
		  error ( "illegal chroma intra prediction mode", 600 );
		  break;
	  }
	}
}
